<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 严格模式用于
                    消除 Javascript 语法的一些不合理、不严谨之处，减少一些怪异行为。
                    消除代码运行的一些不安全之处，保证代码运行的安全。
                    提高编译器效率，增加运行速度。
                    为未来新版本的Javascript做好铺垫。 
        -->

        <!-- 严格模式存在以下限制：
         1、不允许使用未声明的变量
         2、不允许删除对象和变量
         3、不允许删除函数
         4、不允许变量重名
         5、不允许使用八进制
         6、不允许使用转义字符 
         7、不允许对只读属性赋值
         8、不允许对一个使用getter方法读取的属性进行赋值
         9、不允许删除一个不允许删除的属性
         10、变量名不允许使用eval字符串
         11、变量名不允许使用arguments字符串
         12、不允许使用with语句 如   with (Math){x = cos(2)};
         13、在作用域 eval() 创建的变量不能被调用
         14、禁止this关键字指向全局对象。因此使用构造函数时，如果忘了加new，this不再指向全局对象，而是报错。
         -->
    <p>注意：该文件内所有实例均是错误的，此举意在展示在严格模式（strict mode）下javascript会报错的部分情况。</p>

    <button onclick="sm1()">不允许使用未声明的变量。</button>
    <script>
        function sm1(){
            "use strict";
            x = 5;
            console.log(x);//报错
        }
    </script>
    <button onclick="sm2()">不允许删除对象和变量。</button>
    <script>
        function sm2(){
            "use strict";
            var x = 5;
            delete x;//'delete' cannot be called on an identifier in strict mode [javascript]
            console.log(x);//报错
        }
    </script>
    <button onclick="sm3()" >不允许删除函数</button>
    <script>
        function sm3(){
            "use strict";
            function x(){};
            delete x;//'delete' cannot be called on an identifier in strict mode [javascript]
            console.log(x);//报错
        }
    </script>
    <button onclick="sm4()">不允许变量重名</button>
    <script>
        function sm4(){
            "use strict";
            var ax = 5;
            var ax = 6;//'x' has already been declared [javascript]
            console.log(ax);//报错
        }
    </script>

    <button onclick="sm5()">不允许使用八进制</button>
    <script>
        function sm5(){
            "use strict";
            var x = 010;//Octal literals are not allowed in strict mode [javascript]
            console.log(x);//报错
        }
    </script>

    <button onclick="sm6()">不允许使用转义字符</button>
    <script>
        function sm6(){
            "use strict";
            var x = "a\b";//Octal literals are not allowed in strict mode [javascript]
            console.log(x);//报错
        }
    </script>

    <button onclick="sm7()">不允许对只读属性赋值</button>
    <script>
        function sm7(){
            "use strict";
            var x = 5;
            Object.defineProperty(window, "x", {
                writable: false
            });
            x = 6;//Cannot assign to read only property 'x' of object '#<Window>' [javascript]
            console.log(x);//报错
        }
    </script>

    <button onclick="sm8()">不允许对一个使用getter方法读取的属性进行赋值</button>
    <script>
        function sm8(){
            "use strict";
            var x = 5;
            Object.defineProperty(window, "x", {
                get: function(){
                    return x;
                },
                set: function(value){
                    x = value;
                }
            });
        }
    </script>

    <button onclick="sm9()">不允许删除一个不允许删除的属性</button>
    <script>
        function sm9(){
            "use strict";
            var x = 5;
            Object.defineProperty(window, "x", {
                configurable: false
            });
            delete x;//'delete' cannot be called on an identifier in strict mode [javascript]
            console.log(x);//报错
        }
    </script>

    <button onclick="sm10()">变量名不允许使用eval字符串</button>
    <script>
        function sm10(){
            "use strict";
            var eval = 5;//Invalid use of 'eval' in strict mode. [javascript]
            console.log(eval);//报错
        }

        //什么是eval？【 https://www.runoob.com/jsref/jsref-eval.html 】
    </script>

    <button onclick="sm11()">变量名不允许使用arguments字符串</button>
    <script>
        function sm11(){
            "use strict";
            var arguments = 5;//Invalid use of 'arguments' in strict mode. [javascript]
            console.log(arguments);//报错
        }

        //关于js函数参数【 https://www.runoob.com/js/js-function-parameters.html 】
    </script>

    <button onclick="sm12()">不允许使用with语句</button>
    <script>
        function sm12(){
            "use strict";
            with (Math){x = cos(2)};//'with' statements are deprecated in strict mode [javascript]
            console.log(x);//报错
        }
    </script>

    <button onclick="sm13()">在作用域 eval() 创建的变量不能被调用[安全原因]</button>
    <script>
        function sm13(){
            "use strict";
            var x = 5;
            eval("var x = 6;");
            console.log(x);//报错
        }
    </script>
    
    <button onclick="sm14()">禁止this关键字指向全局对象</button>
    <!-- 使用构造函数时，如果忘了加new，this不再指向全局对象，而是报错。 -->
     <script>
        function sm14(){
            "use strict";
            function Person(name){
                this.name = name;
            }
            var person = new Person("Jack");
            console.log(person.name);//Jack
            var person2 = Person("Jack");
            console.log(person2.name);//报错
        }
     </script>

</body>
</html>